﻿using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System.Windows;
using System.Windows.Input;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System;
using HouseKeepingPL.HKService;
using System.Windows.Data;
using System.Windows.Documents;
using GalaSoft.MvvmLight.Messaging;

namespace HouseKeepingPL.ViewModel
{
    public class IncomesViewModel : ViewModelBase
    {
        #region privates
        private ObservableCollection<Income> _incomesList = null;
        private ObservableCollection<ActionType> _actionIncomeTypes; // local action types list
        private bool _isNewIncomeItem = true; // for cleaning outcome input fields
        private bool _cmdActionFlag = false; // action indicator for copy the income (i don't want the collection will be updated until button clicked)
        private User _currentUser = null; // current user logged
        #endregion

        public IncomesViewModel()
        {
            #region messages registrations

            Messenger.Default.Register<ObservableCollection<ActionType>>(this, GetActionList);
            Messenger.Default.Register<User>(this, GetUser);

            #endregion


            // income relay commands
            #region relay commands
            CleanIncomeInputCommand = new RelayCommand(() => CleanIncomeInputCommandExcecute(), () => IsIncomeItemSelected());
            AddIncomeRowCommand = new RelayCommand(() => AddIncomeRowCommandExcecute(), () => !IsIncomeItemSelected());
            DeleteIncomeRowCommand = new RelayCommand(() => DeleteIncomeRowCommandExcecute(), () => IsIncomeItemSelected());
            UpdateIncomeRowCommand = new RelayCommand(() => UpdateIncomeRowCommandExcecute(), () => IsIncomeItemSelected());
            #endregion
        }

        #region messages actions

        /// <summary>
        /// get income list from sender
        /// </summary>
        /// <param name="list"></param>
        private void GetActionList(ObservableCollection<ActionType> list)
        {
            ActionIncomeTypes = list;
        }

        /// <summary>
        /// get user from source, and init if not null
        /// </summary>
        /// <param name="user"></param>
        private void GetUser(User user)
        {
            _currentUser = user;
            if (user != null)
            {
                GetIncomes = _currentUser.Incomes1;
                CleanIncomeInputCommandExcecute();
            }
        }

        #endregion

        #region helpers

        /// <summary>
        /// indicate for the buttons on the income tab whether it "can excecute" or not
        /// </summary>
        /// <returns></returns>
        private bool IsIncomeItemSelected()
        {
            return (!_isNewIncomeItem);
        }

        /// <summary>
        /// checks if income input object is equal to grid object to check if changes done
        /// </summary>
        /// <returns></returns>
        private bool CheckIfIncomeInputEqGrid()
        {
            if ((CurrentlySelectedIncome.Id == CurrentlySelectedIncomeInput.Id) &&
                (CurrentlySelectedIncome.Date == CurrentlySelectedIncomeInput.Date) &&
                (CurrentlySelectedIncome.Comment == CurrentlySelectedIncomeInput.Comment) &&
                (CurrentlySelectedIncome.ActionTypeId == CurrentlySelectedIncomeInput.ActionTypeId) &&
                (CurrentlySelectedIncome.Amount == CurrentlySelectedIncomeInput.Amount))
                return true;

            return false;


        }

        /// <summary>
        /// get the item index in the incomes list
        /// </summary>
        /// <param name="income"></param>
        /// <returns></returns>
        private int LocateIncomeID(Income income)
        {
            bool bFlag = false;
            int index = 0;

            while ((!bFlag) && (index < _incomesList.Count))
            {
                if (_incomesList[index].Id == income.Id)
                {
                    bFlag = true;
                }
                ++index;
            }
            return (--index);


        }


        /// <summary>
        /// Validates the income
        /// </summary>
        /// <returns></returns>
        private bool ValidateIncome()
        {
            if (CurrentlySelectedIncome != null)
            {
                if (ValidateIncomeInputFields(true) == ErrorCode.NoError)
                    return true;
                return false;
            }
            return false;
        }


        private ErrorCode ValidateIncomeInputFields(bool supressMsgBox = false)
        {
            ErrorCode Result = ErrorCode.NoError;
            if (CurrentlySelectedIncomeInput.Date == null)
            {
                Result = ErrorCode.DateFieldError;
                if (!supressMsgBox)
                    MyMessageBox.StopOk("Error occured in Date field", " Validation Error");
            }
            else if (String.IsNullOrEmpty(CurrentlySelectedIncomeInput.Comment))
            {
                Result = ErrorCode.CommentFieldError;
                if (!supressMsgBox)
                    MyMessageBox.StopOk("Error occured in comment field", " Validation Error");
            }
            else if ((CurrentlySelectedIncomeInput.Amount <= 0) || (CurrentlySelectedIncomeInput.Amount > Decimal.MaxValue))
            {
                Result = ErrorCode.AmountFieldError;
                if (!supressMsgBox)
                    MyMessageBox.StopOk("Error occured in Amount field", " Validation Error");
            }
            else if (CurrentlySelectedIncomeInput.ActionTypeId == 0)
            {
                Result = ErrorCode.ActionTypeFieldError;
                if (!supressMsgBox)
                    MyMessageBox.StopOk("Error occured in action field", " Validation Error");

            }


            return Result;



        }


        #endregion

        #region Income


        /// <summary>
        /// Update local collection and DB data
        /// </summary>
        private void UpdateIncomeRowCommandExcecute()
        {
            _cmdActionFlag = true;
            if (!CheckIfIncomeInputEqGrid())
            {
                if (ValidateIncomeInputFields() == ErrorCode.NoError)
                {
                    if ((MyMessageBox.Confirm("Are you sure you want to Update?", "Please confirm") == MessageBoxResult.Yes)) // confirmation
                    {
                        int indexOfUpdatedIncome = LocateIncomeID(CurrentlySelectedIncome); // gets the index of the collection

                        try
                        {
                            ClientProxy.Proxy.UpdateIncome(CurrentlySelectedIncomeInput); // updated db
                        }
                        catch
                        {
                            MyMessageBox.ErrorOk("Error occured while updating the DB", "DB Error");
                        }

                        _incomesList[indexOfUpdatedIncome] = CurrentlySelectedIncomeInput;
                        CleanIncomeInputCommandExcecute();

                        if (_incomesList.Count > 0)
                            CurrentlySelectedIncome = _incomesList[indexOfUpdatedIncome];
                    }
                }
            }
            else
                MyMessageBox.InfoOk("No Changes detected!", "Notification");


            _cmdActionFlag = false;
        }

        /// <summary>
        /// deletes selected row from the DB
        /// </summary>
        private void DeleteIncomeRowCommandExcecute()
        {
            if ((MyMessageBox.Confirm("Are you sure you want to delete?", "Please confirm") == MessageBoxResult.Yes))
            {
                try
                {
                    ClientProxy.Proxy.DeleteIncome(CurrentlySelectedIncome.Id);
                    _incomesList.Remove(CurrentlySelectedIncome);
                }
                catch
                {
                    MyMessageBox.ErrorOk("Error occured while delete from the DB", "DB Error");
                }
            }
        }

        /// <summary>
        /// Add a fields to the DB and the local collecition
        /// </summary>
        private void AddIncomeRowCommandExcecute()
        {
            if (CurrentlySelectedIncomeInput != null)
            {
                if (ValidateIncomeInputFields() == 0)
                {
                    CurrentlySelectedIncomeInput.UsersId = _currentUser.Id;
                    int newID = ClientProxy.Proxy.InsertIncome(CurrentlySelectedIncomeInput);
                    CurrentlySelectedIncomeInput.Id = newID;
                    _incomesList.Add(CurrentlySelectedIncomeInput);
                    CleanIncomeInputCommandExcecute();
                }
            }

        }

        /// <summary>
        /// Clean the input fields and ready for add row
        /// </summary>
        private void CleanIncomeInputCommandExcecute()
        {
            CurrentlySelectedIncome = null;
            _isNewIncomeItem = true;
            IsIncomeItemSelected();

            try
            {
                CurrentlySelectedIncomeInput = new Income()
                {
                    Date = DateTime.Now,
                    Comment = string.Empty,
                    Amount = 0,
                    ActionTypeId = ActionIncomeTypes[0].Id

                };
            }
            catch (NullReferenceException ex)
            {
                MyMessageBox.ErrorOk("no income types available!", "Critical Error");
            }

        }


        

        #region BindProperties

        /// <summary>
        /// from the grid, and update the DB after confirmation
        /// </summary>
        private Income _currentlySelectedIncome;
        public Income CurrentlySelectedIncome
        {
            get
            {
                _isNewIncomeItem = false;
                IsIncomeItemSelected();
                if ((this._currentlySelectedIncome != null) && (_cmdActionFlag == false))
                {
                    _currentlySelectedIncomeInput = new Income() //copy ctor
                    {
                        Id = this._currentlySelectedIncome.Id,
                        UsersId = _currentUser.Id,
                        Date = this._currentlySelectedIncome.Date,
                        Amount = this._currentlySelectedIncome.Amount,
                        Comment = this._currentlySelectedIncome.Comment,
                        ActionTypeId = this._currentlySelectedIncome.ActionTypeId

                    };
                }
                RaisePropertyChanged("CurrentlySelectedIncomeInput");
                return this._currentlySelectedIncome;
            }
            set
            {
                this._currentlySelectedIncome = value;

                RaisePropertyChanged("CurrentlySelectedIncome");
            }
        }

        /// <summary>
        /// binded to the input controls
        /// </summary>
        private Income _currentlySelectedIncomeInput;
        public Income CurrentlySelectedIncomeInput
        {
            get
            {
                return this._currentlySelectedIncomeInput;
            }
            set
            {

                if (_currentlySelectedIncomeInput == null)
                {
                    _currentlySelectedIncomeInput = new Income()
                    {
                        Date = DateTime.Now,
                        Comment = string.Empty,
                        Amount = 0,
                        ActionTypeId = ActionIncomeTypes[0].Id
                    };

                }


                this._currentlySelectedIncomeInput = value;
                RaisePropertyChanged("CurrentlySelectedIncomeInput");
            }
        }


        public ObservableCollection<Income> GetIncomes
        {
            get
            {
                return _incomesList;
            }
            set
            {
                _incomesList = value;
                RaisePropertyChanged("GetIncomes");
            }


        }
        public ObservableCollection<ActionType> ActionIncomeTypes
        {
            get
            {
                return _actionIncomeTypes;
            }
            set
            {
                _actionIncomeTypes = value;
                RaisePropertyChanged("ActionIncomeTypes");
            }
        }
        private ActionType _CurrentlySelectedActionIncomeType;
        public ActionType CurrentlySelectedActionIncomeType
        {
            get { return _CurrentlySelectedActionIncomeType; }
            set { _CurrentlySelectedActionIncomeType = value; }
        }

        #endregion


        #endregion

        #region Command properties
        public ICommand CleanIncomeInputCommand { get; private set; }
        public ICommand AddIncomeRowCommand { get; private set; }
        public ICommand DeleteIncomeRowCommand { get; private set; }
        public ICommand UpdateIncomeRowCommand { get; private set; }

        #endregion
    }
}